/*
 * random_test
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "random_test.h"
#include "../slab/mm.h"

int fix_sizes[] = {32,64,128,256,512,1024,2048,4096,8192,16384};

struct timeval time1, time2;

int data[RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES];

void run_random_test()
{
    int i=0, size = 0, time = 0, total_bytes = 0;
    float mem_util = 0.0f;
    FILE* fp1 = 0;

    fp1 = fopen("test_random1","a");
    if (!fp1)
    {
        fprintf(stderr, "can not open file for logging!");
        exit (1);
    }

    // you can un-comment the following line to get true random data every time
    srandom(random());

    printf("using libc, please wait...");fflush(stdout);

    gettimeofday(&time1, 0);

    total_bytes = 0;

    for (i = 0; i<RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES; ++i)
    {
        if (i < RANDOM_SIZED_MM_OP_TIMES)
        {
            size = (int)(random()/((double)RAND_MAX)*MAX_RANDOM_MALLOC_SIZE);
            total_bytes += size;
            data[i] = (int)malloc(size);
            memset((void*)(data[i]),'A',size);
        }
        else
        {
            size = fix_sizes[i%(sizeof(fix_sizes)/4)];
            total_bytes += size;
            data[i] = (int)malloc(size);
            memset((void*)(data[i]),'A',size);
        }
    }

    for (i = 0; i<RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES; ++i)
    {
        free((void*)(data[i]));
    }

    gettimeofday(&time2, 0);

    printf("done\n");

    time = abs(time2.tv_usec-time1.tv_usec);
    printf("time=%dus\t\tthroughput=%.2g\n",
            time,
            (RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES)*2.0f*1000000/time);
    fprintf(fp1,"%.4g ",
            (RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES)*2.0f*1000000/time);

    printf("initializing our slab implementation, please wait...");fflush(stdout);

    mm_init(true);

    printf("done\n");

    printf("using our slab implementation, please wait...");fflush(stdout);

    gettimeofday(&time1, 0);

    total_bytes = 0;

    for (i = 0; i<RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES; ++i)
    {
        if (i < RANDOM_SIZED_MM_OP_TIMES)
        {
            size = (int)(random()/((double)RAND_MAX)*MAX_RANDOM_MALLOC_SIZE);
            total_bytes += size;
            data[i] = (int)mm_malloc(size);
            memset((void*)(data[i]),'A',size);
        }
        else
        {
            size = fix_sizes[i%(sizeof(fix_sizes)/4)];
            total_bytes += size;
            data[i] = (int)mm_malloc(size);
            memset((void*)(data[i]),'A',size);
        }
    }

    for (i = 0; i<RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES; ++i)
    {
        mm_free((void*)(data[i]));
    }

    gettimeofday(&time2, 0);

    printf("done\n");

    time = abs(time2.tv_usec-time1.tv_usec);
    mem_util = total_bytes*1.0f/(page_occupied*PAGE_SIZE)*100;
    printf("time=%dus\t\tthroughput=%.2g\t\tutilization=%.2f\n",
            time,
            (RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES)*2.0f*1000000/time,
            mem_util);
    fprintf(fp1,"%.4g %.2f\n",
            (RANDOM_SIZED_MM_OP_TIMES + FIX_SIZED_MM_OP_TIMES)*2.0f*1000000/time,
            mem_util);

    printf("un-initializing our slab implementation, please wait...");fflush(stdout);

    mm_deinit();

    printf("done\n");

    fclose(fp1);
}
